iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
Mobile Development

攜手神隊友ChatGPT:攝護腺自我照護App開發歷程!系列 第 8

D8-Records介面,國際攝護腺症狀評分表輕鬆填_part2

  • 分享至 

  • xImage
  •  

Part1:今日目標

1.問卷鑲嵌介面的設計構想
2.程式實作
3.Dart語言學習: @override注釋
4.介面成果

Part2:今日內容

1.問卷鑲嵌介面的設計構想:

(1) 國際攝護腺症狀評分表(IPSS)由七個問題所組成的,每個問題都對應到攝護腺肥大的症狀。其中,每個問題有五個選項供使用者填答,使用者須依照過去一個月的排尿和儲尿狀況選填,頻率越高則分數越高,代表症狀越嚴重。總分為七個題目的總分加總。總分 0-7 分為症狀輕度、8-19 分為中度,20-35 分則為重度。

https://ithelp.ithome.com.tw/upload/images/20230911/20120073Q0PLDOk6mN.png

(2) 介面設計需求: Score_Page.dart

(1)將問卷的七個題目,和每個題目的選項,以上下滑動視窗顯示在介面上。
(2)針對每題的回答,使用Map(Dictionary)的Key和Value,將每題使用者勾選的選項儲存在變數中,讓程式進行總分計算,並按照總分級距,回傳對應的疾病嚴重程度到App介面。
針對以上,在該Dart檔案,程式架構如下圖:
https://ithelp.ithome.com.tw/upload/images/20230911/20120073MpR30ebfFI.png

2.程式實作

(1)class Question{} 將問卷的七個題目,和每個題目的選項,以上下滑動視窗顯示在介面上
自定義 Dart 類別,代表一個問題的數據結構

// 定義了一個 Dart 類別 Question,用於封裝表示問題的數據
// 包含每個問題的內容(問題內容、選項和鍵值),然後在ScorePageState中創建了一個questions列表,其中包含所有的問題
// 這種設計可以方便地將問題的相關數據組織起來,將多個 Question 對象組成一個問題集合,用於測驗或問卷等應用場景
class Question {
  final String question;  // `final`代表不可變的屬性,代表問題的文字描述
  final List<String> options;  // 代表問題的選項列表,選項以字符串的形式存儲在列表中
  final String key;  // 代表問題的唯一鍵值,將用於識別和查找特定的問題

  // 是該類別的構造函式,接收問題、選項和鍵值作為必要的參數
  // 通過這個構造函式,可以創建一個 Question 對象,並初始化其中的屬性
  Question({required this.question, required this.options, required this.key});
}

(2)Widget buildQuestion(): 用於建立單一個問題的 UI
這段程式碼是用於建立單個問題的 UI 的方法,並處理用戶的選擇。以下是對它的詳細說明:

  • buildQuestion 方法是一個小部件,接受以下參數:

    • question:問題的文字描述。
    • options:問題的選項列表。
    • onOptionSelected:當用戶選擇選項時的回調函式。
    • currentQuestion:當前問題的唯一鍵值,用於識別問題。
  • Column 小部件用於垂直排列問題文本和選項。

  • 問題文本使用 Text 小部件顯示,並設置字體樣式。

  • 使用 options.map 方法將每個選項映射為 ListTile 小部件。

    • 每個 ListTile 包括問題選項的文本 (Text) 和選項的 Radio 按鈕。
    • Radio 按鈕用於表示選項,value 是選項的分數,groupValue 是該問題的當前選擇分數。
    • 當用戶選擇一個選項時,onChanged 回調函式會被觸發,將選擇的分數更新到 scores 映射中,並調用 onOptionSelected 回調函式。

這個方法的主要作用是顯示單個問題,讓用戶選擇選項,並根據用戶的選擇更新 scores 映射,這個映射將用於計算症狀總分。這種設計允許用戶回答多個問題,並在 UI 上即時反映他們的選擇。

// buildQuestion() 方法用於構建單一個問題的 UI,包括問題文本和選項列表,用戶可以通過點擊選項來選擇分數
  Widget buildQuestion(String question, List<String> options, Function(int) onOptionSelected, String currentQuestion) {  // 選項都列出來,讓使用者點選
    return Column(
      children: [
        Text(question, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
        ...options.map((option) {
          int optionScore = options.indexOf(option);  // 第一個選項為0分, 若 options.indexOf(option) + 1: 第一個選項為1分
          return ListTile(
            title: Text(option),  // 顯示選項文字
            leading: Radio(
              value: optionScore,  // 選項的分數值
              groupValue: scores[currentQuestion],   // 當前問題的用戶選擇分數
              onChanged: (int? value) {
                if (value != null) {
                  setState(() {
                    scores[currentQuestion] = value;   // 更新問題的用戶選擇分數
                  });
                  onOptionSelected(value);   // 調用回調函式以處理選擇
                }
              },
            ),
          );
        }).toList(),
      ],
    );
  }

(3)Widget build(): 用於構建整個分數頁面的 UI,包括: 問題列表、症狀總分顯示、儲存按鈕和查看分數歷史圖表build 方法中,它是整個分數頁面的 UI 構建部分,處理以下主要內容:

  • 主題和外觀設定

    • 使用 Theme 小部件設置應用程式的主題風格,包括主要顏色和 AppBar 的背景色。
  • Scaffold 和 AppBar**

    • 使用 Scaffold 小部件構建整個頁面的基本結構,包括背景色。
    • 定義了一個自定義的 AppBar,顯示應用程式的標題為 "國際攝護腺症狀評分表: IPSS"。
  • 問題列表

    • 使用 ListView.builder 構建問題列表,其中每個問題都是通過 buildQuestion 方法構建的。
    • 問題數據來自 questions 列表,並根據索引動態生成問題 UI。
  • 症狀總分顯示

    • 通過 Row 小部件,將症狀總分和症狀嚴重程度顯示在界面上。
    • 症狀總分使用 scores 映射中的值計算,然後顯示在界面上。

與之前提到的 buildQuestion 方法不同,這部分程式碼是分數頁面的整體結構,包括整個界面的佈局、主題風格和按鈕處理。這個 build 方法是 Flutter 小部件生命週期中的一部分,當小部件需要構建其 UI 時會被調用。

@override
// build() 方法用於構建整個分數頁面的 UI,包括: 問題列表、症狀總分顯示、儲存按鈕和查看分數歷史圖表按鈕
// '評分頁面', 症狀總分, 儲存, 查看分數歷史圖表
Widget build(BuildContext context) {
return Theme(
  data: ThemeData(
    // primaryColor: const Color(0xFFC2185B),  // 使用自定義顏色作為主要顏色
      primarySwatch: Colors.pink,  // 主題色彩
      appBarTheme: const AppBarTheme(backgroundColor: Color(0xFFC2185B))  // 使用自定義顏色作為 AppBar 的背景色
  ),
  child: Scaffold(
    backgroundColor: backgroundColor,  // 背景色
    appBar: AppBar(title: const Text('國際攝護腺症狀評分表: IPSS')),
    body: Column(  // 將問題由上到下垂直排列
      children: [
        Expanded(
          // 使用 ListView.builder 構建問題列表,每個問題都是通過 buildQuestion() 方法構建的
          child: ListView.builder(
            itemCount: questions.length,
            itemBuilder: (context, index) {
              var question = questions[index];
              return buildQuestion(
                question.question, // 問題文本
                question.options, // 選項列表
                // 使用 setState 方法來處理問題的選擇,同時更新症狀總分和背景顏色
                (int score) => setState(() => scores[question.key] = score),
                question.key,
              );
            },
          ),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                // 顯示症狀總分
                '症狀總分: ${scores.values.reduce((a, b) => a + b)}',
                style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                // 顯示症狀嚴重程度
                '症狀嚴重程度: ${scores.values.reduce((a, b) => a + b) <= 7 ? '輕度' : (scores.values.reduce((a, b) => a + b) <= 19 ? '中度' : '重度')}',
                style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
            ),
          ],
        ),
      ],
    ),
  ),
);
}

3.Dart語言學習: @override注釋

(1)@override注釋

@override
Widget build(BuildContext context){}
  • @override:這是 Dart 語言提供的一個注釋,用來表示接下來的方法將覆蓋(重寫)父類別中具有相同名稱的方法。這個注釋通常用在子類別中,當你想要重寫父類別中已經存在的方法時。

  • 在上述代碼中,@override 注釋用在 build 方法上,這是一個常見的做法,因為 build 方法是 Flutter 中的一個核心方法,用於構建小部件的 UI。

  • Widget build(BuildContext context):這是一個方法的定義,它在 State 子類別中覆蓋了父類別 StatefulWidgetbuild 方法。在 Flutter 中,build 方法是用於構建小部件的 UI 表示的地方。

  • BuildContext context:這是 build 方法的參數,它提供了上下文信息,允許小部件訪問 Flutter 應用程式的環境和配置。它是一個重要的參數,通常需要在構建 UI 時使用。

總結,@override 注釋告訴編譯器,這個方法將覆蓋父類別的方法,並且該方法用於構建小部件的 UI。當 Flutter 需要重新渲染小部件時,它將調用這個方法來生成新的 UI 表示。

4.介面成果

https://ithelp.ithome.com.tw/upload/images/20230911/20120073sFBfO8QJ3c.png

你所有的努力,不該是為了讓他人佩服,而是讓自己真心以自己為傲
All your efforts should be aimed not at earning admiration from others, but at genuinely making yourself proud.

今天享受了一杯熱可可,工作進度報告也順利~晚上吃了美味又健康的晚餐,平淡的充實的一天,早早睡去明天繼續!


上一篇
D7-Records介面,國際攝護腺症狀評分表輕鬆填_part1
下一篇
D9-Records介面,國際攝護腺症狀評分表輕鬆填_part3
系列文
攜手神隊友ChatGPT:攝護腺自我照護App開發歷程!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言